package JVM;


/**
 * 5. 方法区  "线程共享"  有垃圾回收
 *      5.1 他存储了每一个类的结构信息
 *      5.2 方法区是规范 在不同虚拟机里头实现是不一样的 ，
 *      最典型的是永久代（PermGen  space）和元空间(Metaspace)
 *
 *  供各线程共享的运行时内存区域。它存储了每一个类的结构信息，
 *  方法区包含所有的class和static变量。
 *  方法区中包含的都是在整个程序中永远唯一的元素，如class，static变量。
 *  例如
 *      运行时常量池(Runtime Constant Pool)、
 *      字段和方法数据、构造函数和普通方法的字节码内容。.
 *
 *  上面讲的是规范，在不同虚拟机里头实现是不一样的，
 *  最典型的就是永久代(PermGen space) 和元空间(Metaspace)。
 *    But
 *      实例变量存在堆内存中,和方法区无关
 *
 *      方法区是一种规范，永久代是Hotspot针对这一规范的一种实现
 *   那么在Hotspot(java的虚拟机)下，方法区就等于永久代，也被称为非堆
 *
 * 在out包下  会有一个和src包（.java）几乎雷同的
 *   （.class）在硬盘上   （加载到）到JVM里
 *   变成（.Class）  .Class在方法区
 *
 */
public class 方法区 {//通常说的常量池 指的是运行时常量池  线程共享
    public static final String a;
    public static final String b;
    public static final String aa="123";
    public static final String bb="456";
    public static  String aaa="123";
    public static  String bbb="456";
    static {
        a = "123";
        b = "456";
    }

    public static void main(String[] args) {
        字符串常量池();
    }
    private static void 字符串常量池() {
        String c = "123456";
        String d = a + b;
        System.out.println((c == d)+"\t"+d);//false	123456

        String e=aa+bb;
        System.out.println((c == e)+"\t"+e);//true	123456

        String f=aaa+bbb;
        System.out.println((c == f)+"\t"+f);//false	123456
    }

    /**
     * 包装类的常量池
     * 对象比较自动装箱和自动拆箱，自动装箱常见的就是valueOf这个方法，自动拆箱就是intValue方法。
     * 在它们的源码中有一段神秘的代码值得我们好好看看。
     * 除了两个包装类Long和Double 没有实现这个缓存技术，其它的包装类均实现了它。
     * Integer i=new Integer(50);
     * Integer j=new Integer(50);
     * System.out.println(i==j);  //运行的结果是false
     * Integer i=new Integer.valueOf(100);
     * Integer j=new Integer.valueOf(100);
     * System.out.println(i==j);  //运行的结果是true
     * Integer i=new Integer.valueOf(400);
     * Integer j=new Integer.valueOf(400);
     * System.out.println(i==j);//运行结果是false
     * Integer i=100;
     * Integer j=100;
     * System.out.println(i==j);//运行结果是true
     * 然后再用400这个数试一试，通过实验运行的结果是false，
     *public static Integer valueOf(int i){
     * if(i>=-128&&i<=IntegerCache.high)
     * return IntegerCache.cache[i+128];
     * else return new Integer(i);
     * }
     * 通过看源码能够知道整数类型在-128~127之间时，会使用缓存。
     * 造成的效果就是，如果已经创建了一个相同的整数，
     * 使用valueOf创建第二次时，不会使用new 关键字，
     * 而是用已经缓存的对象。所以使用valueOf方法创建两次对象，
     * 若对应数值相同，且数值在-128~127之间时，两个对象指向同一个地址。
     * 使用Integer i=400这样的方法创建Integer对象与使用valueOf方法的效果是一样的,
     * 若要比较，使用compareTo或者equals方法是更好的
     */
}
